package com.piz.service.orderservice;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;

import com.piz.dao.order.OrderDao;
import com.piz.dao.product.ProductCategoryDao;
import com.piz.dao.product.ProductDao;
import com.piz.model.ItemDetails;
import com.piz.model.ItemPricing;
import com.piz.model.OfferCoupon;
import com.piz.service.common.AppCache;
import com.piz.service.common.UnexpectedServiceException;
import com.piz.service.model.Cart;
import com.piz.service.model.PizzaCategoryBean;
import com.piz.service.model.PizzaItem;
import com.piz.service.model.PizzaPrice;
import com.piz.service.model.SideCategoryBean;
import com.piz.service.model.SideItem;
import com.piz.service.productservice.ProductService;

public class OrderService {
	
	@Autowired
	ProductDao productDao;
	
	@Autowired
	ProductService productService;
	
	@Autowired
	ProductCategoryDao categoryDao;
	
	@Autowired
	OrderDao orderDao;
	
	public List<PizzaItem> fetchAllPizzas() throws UnexpectedServiceException
	{
		List<ItemDetails> pizzaItems = productDao.findAllPizzas();
		List<PizzaItem> pizzas = new ArrayList<PizzaItem>();
		Map<Integer, String> cat = productService.fetchProductCategoryMap();
		Map<Integer, String> tasteMap = productService.fetchPizzaTasteMap();
		for(ItemDetails item : pizzaItems)
		{
			List<ItemPricing> itemprices = item.getPrices();
			List<PizzaPrice> pizzaprices = new ArrayList<PizzaPrice>();
			String priceString = "";
			for(ItemPricing itemprice : itemprices)
			{
				PizzaPrice pizzaPrice = new PizzaPrice(itemprice.getServe().getId()
						, itemprice.getServe().getBase(), itemprice.getPrice());
				pizzaprices.add(pizzaPrice);
				priceString = priceString + itemprice.getPrice().toString() + " ";
			}
			PizzaItem pizza = new PizzaItem(item.getId(), item.getName(), item.getImage(), item.getClassificationId(), 
					cat.get(item.getCategoryId().intValue()), item.getTasteId(), 
					tasteMap.get(item.getTasteId().intValue()), pizzaprices, priceString);
			pizza.setDescription(item.getDescription());
			pizzas.add(pizza);
		}
		
		return pizzas;
	}
	
	public List<SideItem> fetchAllSides() throws UnexpectedServiceException
	{
		List<ItemDetails> sideItems = productDao.findAllSides();
		Map<Integer, String> catMap = productService.fetchProductCategoryMap();
		List<SideItem> sides = new ArrayList<SideItem>();
		for(ItemDetails item : sideItems)
		{
			SideItem sideItem = new SideItem(item.getId(), item.getName(), item.getImage(), item.getPrices().get(0).getPrice(), 
					item.getClassificationId(),catMap.get(item.getClassificationId().intValue()), 1);
			sides.add(sideItem);
		}
		return sides;
	}
	
	public PizzaItem fetchPizzaItemById(Long pizzaId) throws UnexpectedServiceException
	{
		ItemDetails item = productService.fetchPizzaById(pizzaId);
		Map<Integer, String> cat = productService.fetchProductCategoryMap();
		Map<Integer, String> tasteMap = productService.fetchPizzaTasteMap();
		List<PizzaPrice> pizzaprices = new ArrayList<PizzaPrice>();
		List<ItemPricing> prices = item.getPrices();
		Double defaultPrice = null;
		for(ItemPricing itemprice : prices)
		{
			PizzaPrice pizzaPrice = new PizzaPrice(itemprice.getServe().getId()
					, itemprice.getServe().getBase(), itemprice.getPrice());
			pizzaprices.add(pizzaPrice);
			
			if(itemprice.getServe().getId().equals(2l)){
				defaultPrice = itemprice.getPrice();
			}
		}
		Long[] toppings = new Long[0];
		PizzaItem pizza = new PizzaItem(item.getId(), item.getName(), item.getImage(), item.getClassificationId(), 
				cat.get(item.getCategoryId().intValue()), item.getTasteId(), 
				tasteMap.get(item.getTasteId().intValue()), pizzaprices, null);
		pizza.setToppings(toppings);
		pizza.setQuantity(1);
		pizza.setDescription(item.getDescription());
		pizza.setNetPrice(defaultPrice);
		return pizza;
	}
	
	public SideItem fetchSideItemById(Long id) throws UnexpectedServiceException
	{
		Map<Integer, String> cat = productService.fetchProductCategoryMap();
		ItemDetails item = productService.fetchPizzaById(id);
		SideItem side = new SideItem(item.getId(),item.getName(),item.getImage(),
									item.getPrices().get(0).getPrice(),item.getCategoryId(),cat.get(item.getCategoryId()),1);
		
		return side;
		
	}
	
	public Double calculateNetPizzaPrice(PizzaItem pizzaItem) throws UnexpectedServiceException
	{
		PizzaItem pizza = fetchPizzaItemById(pizzaItem.getPizzaId());
		pizza.setServeId(pizzaItem.getServeId());
		pizza.setQuantity(pizzaItem.getQuantity());
		pizza.setToppings(pizzaItem.getToppings());
		Double price = 0.0;
		if(pizza.getServeId() == null)
		{
			pizza.setServeId(2l);
		}
		if(pizza.getQuantity() == null)
		{
			pizza.setQuantity(1);
		}
		for(PizzaPrice prices : pizza.getPrices())
		{
			if(prices.getServeId().equals(pizza.getServeId()))
			{
				price = prices.getPrice();
			}
		}
		if((pizza!=null) && pizza.getToppings()!=null && (pizza.getToppings().length >0))
		{
			for(ItemDetails topps : fetchToppingById(pizzaItem.getToppings()))
			{
				if(topps != null)
				{
					for(ItemPricing topPrice :  topps.getPrices())
					{
						if(topPrice.getServe().getId().equals(pizza.getServeId()))
						{
							price = price + topPrice.getPrice();
						}
					}
				}
			}
		}
		price *= pizza.getQuantity();
		return price;
	}
	
	public List<PizzaItem> fetchPizzasByCategory(Integer catId) throws UnexpectedServiceException
	{
		List<PizzaItem> pizzaItems = fetchAllPizzas();
		List<PizzaItem> pizzaByCat = new ArrayList<PizzaItem>();
		for(PizzaItem pizza : pizzaItems)
		{
			if(pizza.getCategoryId().intValue() == catId)
			{
				pizzaByCat.add(pizza);
			}
		}
		return pizzaByCat;
	}
	
	public List<SideItem> fetchSideByCategory(Integer catId) throws UnexpectedServiceException
	{
		List<SideItem> sides = fetchAllSides();
		List<SideItem> sideByCat = new ArrayList<SideItem>();
		for(SideItem side : sides)
		{
			if(side.getCategoryId().intValue() == catId)
			{
				sideByCat.add(side);
			}
		}
		
		return sideByCat;
	}
	
	public List<PizzaCategoryBean> fetchPizzaCategoryBeans() throws UnexpectedServiceException
	{
		List<PizzaCategoryBean> beans = new ArrayList<PizzaCategoryBean>();
		Map<Integer, String> cat = productService.fetchProductCategoryMap();
		for (Integer categoryId : cat.keySet())
		{
			List<PizzaItem> pizzas = fetchPizzasByCategory(categoryId);
			if(pizzas != null && pizzas.size() >0)
			{
				String catName = cat.get(categoryId);
				PizzaCategoryBean categoryBean = new PizzaCategoryBean(catName,categoryId.longValue(), 
		    	productService.getClassificationDao().fetchClassById(categoryId.longValue()).getImage(),pizzas);
				beans.add(categoryBean);
			}
		}
		
		return beans;
	}
	
	
	public List<SideCategoryBean> fetchSideCategoryBean() throws UnexpectedServiceException {
		List<SideCategoryBean> beans = new ArrayList<SideCategoryBean>();
		Map<Integer, String> cat = productService.fetchProductCategoryMap();
		for (Integer categoryId : cat.keySet()) {
			List<SideItem> sides = fetchSideByCategory(categoryId);
			if(sides != null && sides.size() > 0)
			{
				String catName = cat.get(categoryId);
				SideCategoryBean categoryBean = new SideCategoryBean(catName, categoryId.longValue(),
		    		productService.getClassificationDao().fetchClassById(categoryId.longValue()).getImage(),
		    		sides);
				beans.add(categoryBean);
			}
		}
		return beans;
	}
	
	
	public List<ItemDetails> fetchToppingById(Long[] toppIds)
	{
		List<ItemDetails> alltopps = productDao.findAllToppings();
		List<ItemDetails> filterTops = new ArrayList<ItemDetails>();
		for(Long topp : toppIds)
		{
			for(ItemDetails toppItem : alltopps)
			{
				if(topp.equals(toppItem.getId()))
				{
					filterTops.add(toppItem);
				}
			}
		}
		return (List<ItemDetails>) filterTops;
		
	}
	public boolean addtoCart(PizzaItem pizza) throws UnexpectedServiceException
	{
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		if(cart == null)
		{
			cart = new Cart();
		}
		if(cart.getPizzas() == null)
		{
			cart.setPizzas(new ArrayList<PizzaItem>());
		}
		PizzaItem pizzaItem = fetchPizzaItemById(pizza.getPizzaId());
		pizzaItem.setServeId(pizza.getServeId());
		pizzaItem.setQuantity(pizza.getQuantity());
		pizzaItem.setToppings(pizza.getToppings());
		pizzaItem.setNetPrice(calculateNetPizzaPrice(pizzaItem));
		if(cart != null)
		{
			cart.getPizzas().add(pizzaItem);
		}
		cart.setTotalPrice(cart.getTotalPrice()+ pizzaItem.getNetPrice());
		cart.setTax(cart.getTotalPrice()*10/100);
		cart.setGrandTotal(cart.getTotalPrice() +  cart.getTax());
		
		AppCache.getInstance().setCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId(), cart);
		return true;
	}
	
	public boolean addSidetoCart(SideItem side) throws UnexpectedServiceException
	{
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		if(cart == null)
		{
			cart = new Cart();
		}
		if(cart.getSides() == null)
		{
			cart.setSides(new ArrayList<SideItem>());
		}
		SideItem sideItem = fetchSideItemById(side.getId());
		sideItem.setQuantity(side.getQuantity());
		sideItem.setNetPrice(sideItem.getPrice()*side.getQuantity());
		if(cart != null)
		{
			cart.getSides().add(sideItem);
		}
		
		cart.setTotalPrice(cart.getTotalPrice()+ sideItem.getNetPrice());
		cart.setTax(cart.getTotalPrice()*10/100);
		cart.setGrandTotal(cart.getTotalPrice() +  cart.getTax());
		return true;
	}
	
	public boolean removeFromCart(int index, boolean removeSide, boolean removeDiscount)
	{
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		if(cart != null)
		{
			if(removeSide)
			{
				List<SideItem> sides = new ArrayList<SideItem>(cart.getSides());
				if(sides !=null && sides.size()>0)
				{
					SideItem side = cart.getSides().get(index);
					cart.getSides().remove(index);
					cart.setTotalPrice(cart.getTotalPrice() - side.getNetPrice());
				}
			}
			
			else if(removeDiscount)
			{
				List<OfferCoupon> coupons = new ArrayList<OfferCoupon>(cart.getCoupons());
				if(coupons != null && coupons.size() > 0)
				{
					OfferCoupon c = cart.getCoupons().get(index);
					cart.getCoupons().remove(index);
					cart.setGrandTotal(cart.getGrandTotal() + c.getDiscountAmt());
					cart.setTotal_discount(cart.getTotal_discount() - c.getDiscountAmt());
				}
			}
			
			else{
				List<PizzaItem> pizzas =  new ArrayList<PizzaItem>(cart.getPizzas());
				if(pizzas != null && pizzas.size() > 0)
				{
					PizzaItem pizza =  cart.getPizzas().get(index);
					cart.getPizzas().remove(index);
					cart.setTotalPrice(cart.getTotalPrice() - pizza.getNetPrice());
				}
			}
			
			cart.setTax(cart.getTotalPrice()*10/100);
			cart.setGrandTotal(cart.getTotalPrice() +  cart.getTax());
			
		}
		AppCache.getInstance().setCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId(), cart);
		return true;
	}
	
	public boolean calculateCartRates()
	{
		Double totalPrice = 0.0;
		Double tax = 0.0;
		Double grandTotal = 0.0;
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		if(cart != null)
		{
			List<PizzaItem> pizzas =  cart.getPizzas();
			if(pizzas != null && pizzas.size() > 0)
			{
				for(PizzaItem pizza : pizzas)
				{
				 totalPrice+= pizza.getNetPrice();
				}
			}
		}
		
		tax = (totalPrice * 10)/100;
		grandTotal = totalPrice  + tax;
		cart.setTotalPrice(totalPrice);
		cart.setTax(tax);
		cart.setGrandTotal(grandTotal);
		AppCache.getInstance().setCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId(), cart);
		return true;
	}
	
	public Long addDiscountCoupontoCart(String coupon_code)
	{
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		OfferCoupon c = orderDao.fetchOfferByCouponCode(coupon_code);
		if(c!= null)
		{
			List<OfferCoupon> coupons = cart.getCoupons();
			if(coupons == null)
			{
			coupons = new ArrayList<OfferCoupon>();
			}
			c.setDiscountAmt(cart.getTotalPrice()*c.getDiscount()/100);
			coupons.add(c);
			Double total = cart.getGrandTotal() - (c.getDiscountAmt());
			Double total_discount = cart.getTotal_discount() + c.getDiscountAmt();
			cart.setGrandTotal(total);
			cart.setCoupons(coupons);
			cart.setTotal_discount(total_discount);
			return c.getId();
		}
		else
		{
			return null;
		}
	}
	
	public String isCouponValid(String coupon_code)
	{
		OfferCoupon c = orderDao.fetchOfferByCouponCode(coupon_code);
		Cart cart = (Cart) AppCache.getInstance().getCartInfo(RequestContextHolder.currentRequestAttributes().getSessionId());
		String error = null;
		boolean valid = true;
		if(c == null)
		{
			valid = false;
			error = "Coupon code is not valid. Enter a valid code.";
			return error;
		}
		if(valid)
		{
			List<OfferCoupon> coupons = cart.getCoupons();
			if(coupons != null)
			{
				for(OfferCoupon cc : coupons)
				{
					if(cc.getCouponCode().equalsIgnoreCase(coupon_code))
					{
						valid = false;
						error = "Coupon is already added in order.";
						return error;
					}
				}
			}
		}
		return null;
	}
}
